package com.sky.pay.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Data;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
 * @author yangsk
 * 微信支付的基本参数类,用于读取yaml文件的属性参数值
 */
@Configuration
@Data
@PropertySource("classpath:application.yaml")
@ConfigurationProperties(prefix = "weixinPay")
public class WeixinPayConfig {
    private String  merchantId;
    private String  merchantSerialNo;
    private String  privateKeypath;
    private String  apiV3Key;
    private String  appid;
    private String  domain;
    private String  notifyDomain;

    /**
     * 获取根目录下的商户文件中的私钥
     */
    private PrivateKey getMerchantPriviteKey(String fileName){
        PrivateKey merchantPrivateKey = null;
        try{
            merchantPrivateKey = PemUtil.loadPrivateKey(
                    new FileInputStream(fileName));
        }catch (Exception e){
            new RuntimeException("获取根目录下的商户文件的商户私钥失败",e);
        }
        return merchantPrivateKey;
    }

    /**
     * 定时自动获取商户证书
     * @return
     * @throws Exception
     */
    @Bean
    public CertificatesManager certificatesManager()throws Exception{
        //获取商户私钥
        PrivateKey merchantPrivateKey = this.getMerchantPriviteKey(privateKeypath);
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 创建钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(merchantSerialNo, merchantPrivateKey);
        // 身份认证对象,微信返回结果，服务需要对结果进行验证，这个结果是否是微信的返回
        WechatPay2Credentials vechatPay2Credentials = new WechatPay2Credentials(merchantId,privateKeySigner);
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(merchantId, vechatPay2Credentials,apiV3Key.getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        return certificatesManager;
    }



    /**
     * 构造微信请求对象
     * @throws Exception
     */
    public CloseableHttpClient getWinxinClient() throws Exception{
        //获取商户私钥
        PrivateKey merchantPrivateKey = this.getMerchantPriviteKey(privateKeypath);
        // 从证书管理器中获取verifier签名认证器
        Verifier verifier = certificatesManager().getVerifier(merchantId);

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier));
           // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        // 签名：对公钥对request发出的请求进行签名，微信接收到数据后，会用密钥度对数据进行签名验证，解密出数据
        // 验签：微信接收到数据后，用私钥对影响数据进行签名并返回给这里的服务，服务需要用公钥对数据进行签名验证，解密出响应数据
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }
}
